﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Text.RegularExpressions;

namespace AvalonAdmin.Helpers
{

    #region 使用方法
    //// 1. 解析域名
    //string[] googleIps = NetworkHelper.ResolveToIP("google.com");
    //Console.WriteLine("Google的IP地址：");
    //    foreach (string ip in googleIps)
    //    {
    //        Console.WriteLine($" - {ip}");
    //    }

    //// 2. 解析带端口的域名
    //string[] exampleIps = NetworkHelper.ResolveToIP("example.com:8080");
    //Console.WriteLine("\nexample.com的IP地址：");
    //foreach (string ip in exampleIps)
    //{
    //Console.WriteLine($" - {ip}");
    //}

    //// 3. 解析带协议的URL
    //string[] githubIps = NetworkHelper.ResolveToIP("https://github.com");
    //Console.WriteLine("\ngithub.com的IP地址：");
    //foreach (string ip in githubIps)
    //{
    //Console.WriteLine($" - {ip}");
    //}

    //// 4. 解析IP地址（直接返回）
    //string[] directIps = NetworkHelper.ResolveToIP("8.8.8.8");
    //Console.WriteLine("\n8.8.8.8的解析结果：");
    //foreach (string ip in directIps)
    //{
    //Console.WriteLine($" - {ip}");
    //}

    //// 5. 仅获取IPv6地址
    //string[] ipv6Ips = NetworkHelper.ResolveToIP("ipv6.google.com", AddressFamily.InterNetworkV6);
    //Console.WriteLine("\ngoogle.com的IPv6地址：");
    //foreach (string ip in ipv6Ips)
    //{
    //Console.WriteLine($" - {ip}");
    //}
    #endregion

    /// <summary>
    /// 根据 IP 端口或者域名获取实际 IP 地址（即解析域名对应的 IP 地址）
    /// </summary>
    public static class NetworkHelper
    {
        /// <summary>
        /// 根据输入的域名或IP地址，获取对应的实际IP地址列表（支持IPv4和IPv6）
        /// </summary>
        /// <param name="input">域名（如"example.com"）或IP地址（如"192.168.1.1"）</param>
        /// <param name="addressFamily">可选的地址族过滤（默认返回所有类型）</param>
        /// <returns>解析结果（IP地址列表或错误信息）</returns>
        public static string[] ResolveToIP(string input, AddressFamily? addressFamily = null)
        {
            try
            {
                // 1. 提取主机名（如果包含端口或协议头）
                string host = ExtractHost(input);

                // 2. 检查是否为有效的IP地址格式（直接返回）
                if (IPAddress.TryParse(host, out IPAddress ip))
                {
                    return new[] { ip.ToString() };
                }

                // 3. 域名解析（通过DNS）
                IPAddress[] addresses = Dns.GetHostAddresses(host);

                // 4. 过滤指定地址族的IP
                if (addressFamily.HasValue)
                {
                    addresses = Array.FindAll(addresses, addr => addr.AddressFamily == addressFamily.Value);
                }

                return Array.ConvertAll(addresses, addr => addr.ToString());
            }
            catch (SocketException ex)
            {
                return new[] { $"错误：{ex.SocketErrorCode} - {ex.Message}" };
            }
            catch (Exception ex)
            {
                return new[] { $"错误：{ex.Message}" };
            }
        }

        /// <summary>
        /// 从输入中提取主机名（去除协议头和端口）
        /// </summary>
        private static string ExtractHost(string input)
        {
            if (string.IsNullOrWhiteSpace(input))
                return input;

            // 去除协议头（如"http://"或"https://"）
            if (input.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
                input = input.Substring(7);
            else if (input.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
                input = input.Substring(8);

            // 去除端口部分（如":8080"）
            int portIndex = input.IndexOf(':');
            if (portIndex > 0)
            {
                input = input.Substring(0, portIndex);
            }

            // 去除路径部分（如"/path"）
            int pathIndex = input.IndexOf('/');
            if (pathIndex > 0)
            {
                input = input.Substring(0, pathIndex);
            }

            return input.Trim();
        }

        /// <summary>
        /// 获取第一个可用的 IP 地址（通过尝试连接指定端口）
        /// 测试 HTTP 服务（TCP/80）:
        /// var result = await NetworkHelper.GetFirstAvailableIP("example.com", 80);
        /// Console.WriteLine($"可用 IP：{result}");
        /// 测试 DNS 服务（UDP/53）:
        /// var result = await NetworkHelper.GetFirstAvailableIP("8.8.8.8", 53, 1000, ProtocolType.Udp);
        /// Console.WriteLine($"DNS 服务器状态：{result}");
        /// 测试自定义 UDP 服务：
        /// var result = await NetworkHelper.GetFirstAvailableIP("192.168.1.1", 1234, 2000, ProtocolType.Udp, "PING");
        /// Console.WriteLine($"UDP 服务状态：{result}");
        /// </summary>
        /// <param name="input">域名或 IP 地址</param>
        /// <param name="port">目标端口（默认 80）</param>
        /// <param name="timeoutMs">超时时间（毫秒）</param>
        /// <param name="protocol">协议类型（TCP 或 UDP）</param>
        /// <param name="udpTestData">UDP 测试数据（可选）</param>
        /// <returns>可用的 IP 地址或错误信息</returns>
        public static async Task<string> GetFirstAvailableIP(string input, int port = 80, int timeoutMs = 1000, ProtocolType protocol = ProtocolType.Tcp, string udpTestData = "TEST")
        {
            try
            {
                if (string.IsNullOrWhiteSpace(input))
                    return "错误：输入为空";

                // 解析所有 IP 地址
                string[] ipAddresses = ResolveToIP(input);

                // 过滤错误信息，提取有效 IP
                var validIps = ipAddresses
                    .Where(ip => !ip.StartsWith("错误"))
                    .ToList();

                if (!validIps.Any())
                    return ipAddresses.FirstOrDefault() ?? "无可用 IP";

                // 按顺序尝试每个 IP（避免并行导致资源耗尽）
                foreach (string ip in validIps)
                {
                    try
                    {
                        using var cts = new CancellationTokenSource(timeoutMs);

                        if (protocol == ProtocolType.Tcp)
                        {
                            // TCP 连接测试
                            using TcpClient client = new TcpClient();
                            await client.ConnectAsync(IPAddress.Parse(ip), port, cts.Token);
                            return ip; // 连接成功，返回 IP
                        }
                        else
                        {
                            // UDP 连接测试（需要目标服务回包）
                            using UdpClient client = new UdpClient();
                            client.Client.SendTimeout = timeoutMs;
                            client.Client.ReceiveTimeout = timeoutMs;

                            var endpoint = new IPEndPoint(IPAddress.Parse(ip), port);
                            byte[] data = Encoding.UTF8.GetBytes(udpTestData);

                            await client.SendAsync(data, data.Length, endpoint);

                            // 尝试接收响应（某些服务可能不响应）
                            var receiveEndpoint = new IPEndPoint(IPAddress.Any, 0);
                            var result = await client.ReceiveAsync();

                            if (result.Buffer.Length > 0)
                                return ip;
                        }
                    }
                    catch (SocketException ex) when (ex.SocketErrorCode == SocketError.TimedOut)
                    {
                        // 超时，尝试下一个 IP
                        continue;
                    }
                    catch (OperationCanceledException)
                    {
                        // 超时，尝试下一个 IP
                        continue;
                    }
                    catch
                    {
                        // 其他错误，尝试下一个 IP
                        continue;
                    }
                }

                return "失败：所有 IP 均不可用";
            }
            catch (Exception ex)
            {
                return $"错误：{ex.Message}";
            }
        }
    }
}
